package com.crazymaker.springcloud.reactive.rpc;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * JDK反射处理器
 */
@Slf4j
public class MockInvocationHandler implements InvocationHandler {

    private Map<Method, RpcMethodHandler> dispatch = new HashMap<>();

    public MockInvocationHandler() {
        // 扫描自定义的注解

    }

    public static <T> T newInstance(Class<T> clazz) {
        MockInvocationHandler handler = new MockInvocationHandler();
        RequestMapping reqMapping = clazz.getAnnotation(RequestMapping.class);
        if (reqMapping != null) {
            String contextPath = reqMapping.value()[0];
            Map<Method, RpcMethodHandler> methodDispatch = new HashMap<>();
            for (Method method : clazz.getMethods()) {
                GetMapping methodMapping = method.getAnnotation(GetMapping.class);
                String uri = methodMapping.value()[0];

                MockRpcMethodHandler methodHandler = new MockRpcMethodHandler(contextPath, uri);
                methodDispatch.put(method, methodHandler);
            }
            handler.setDispatch(methodDispatch);
            return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz}, handler);
        }
        return null;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("method->{} is called", method.getName());
        return dispatch.get(method).invoke(args);
    }

    public void setDispatch(Map<Method, RpcMethodHandler> dispatch) {
        this.dispatch = dispatch;
    }
}
